package com.ruoyi.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.PageResult;
import com.ruoyi.common.Result;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.domain.Templates;
import com.ruoyi.domain.TemplatesDTO;
import com.ruoyi.service.TemplatesService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.server.ResponseStatusException;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;

/**
 * @Classname TemplatesController
 * @Description TODO
 * @Date 2025/3/20 09:38
 * @Created by xxx
 */
@RestController
@RequestMapping("/api/v1/templates")
@Data
@RequiredArgsConstructor
@Api(tags = "模板管理")
@Slf4j
public class TemplatesController {
    private final TemplatesService templatesService;
    //private Long userId = 1L;
    //private Long userId = SecurityUtils.getUserId();


    @GetMapping(value = "/all")
    @ApiOperation(value = "获取所有模板", notes = "获取所有模板")
    public Result getAllTemplates() {
        if (SecurityUtils.getUserId() == null) {
            return Result.error("请先登录");
        }
        return templatesService.listAll();
    }

    @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @ApiOperation(value = "上传模板文件", notes = "上传模板文件")
    public Result upload(@RequestParam("title") String title,
                         @RequestParam("file") MultipartFile file) {
        Long userId = SecurityUtils.getUserId();
        if (userId == null) {
            return Result.error("请先登录");
        }
        TemplatesDTO templatesDTO = TemplatesDTO.builder()
                .title(title)
                .file(file)
                .createBy(userId)
                .createTime(LocalDateTime.now())
                .build();
        boolean result = templatesService.upload(templatesDTO);

        return result ? Result.success() : Result.error("上传失败");
    }

    @GetMapping(value = "/list")
    @ApiOperation(value = "获取模板列表", notes = "获取模板列表")
    public Result list(TemplatesDTO templatesDTO) {
        Long userId = SecurityUtils.getUserId();
        if (userId == null) {
            return Result.error("请先登录");
        }
        templatesDTO.setCreateBy(userId);
        templatesDTO.setCreateTime(LocalDateTime.now());
        PageResult pageResult = templatesService.list(templatesDTO);
        return Result.success(pageResult);
    }

    @DeleteMapping(value = "/delete")
    @ApiOperation(value = "删除模板", notes = "删除模板")
    public Result delete(@RequestParam("id") Integer id) {
        Long userId = SecurityUtils.getUserId();
        if (userId == null) {
            return Result.error("请先登录");
        }
        boolean result = templatesService.delete(id, userId);
        return result ? Result.success() : Result.error("删除失败");
    }

    @PostMapping(value = "/download")
    @ApiOperation(value = "下载模板文件", notes = "下载模板文件")
    public void downloadTemplate(
            @RequestParam("id") Integer templateId,
            HttpServletResponse response) {
        Long userId = SecurityUtils.getUserId();
        if (userId == null) {
            sendErrorResponse(response, "请先登录");
            return;
        }
        log.info("下载模板文件，templateId:{}, userId:{}", templateId, userId);
        response.setContentType("application/octet-stream");
        response.setStatus(HttpStatus.OK.value());
        try {
            // 验证参数有效性
            if (templateId == null || templateId <= 0) {
                sendErrorResponse(response, "无效的模板ID");
                return;
            }

            Templates templates = templatesService.getDownloadPath(templateId, userId);
            Path filePath = Paths.get(templates.getFilePath());
            String fileName = String.valueOf(filePath.getFileName());
            fileName = templates.getTitle() + fileName.substring(fileName.lastIndexOf("."));
            // 检查文件是否存在
            if (!Files.exists(filePath)) {
                sendErrorResponse(response, "文件不存在");
                return;
            }
            // 成功响应文件流
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name())
                    .replaceAll("\\+", "%20");
            response.setHeader("Content-Disposition",
                    "attachment; filename=\"" + encodedFileName + "\"");

            Files.copy(filePath, response.getOutputStream());
            response.flushBuffer();
        } catch (IOException e) {
            sendErrorResponse(response, "文件读取失败");
        }
    }

    private void sendErrorResponse(HttpServletResponse response, String message) {
        Integer statusCode = HttpStatus.BAD_REQUEST.value();
        try {
            // 设置字符编码和内容类型
            response.setCharacterEncoding(StandardCharsets.UTF_8.name());
            response.setContentType(MediaType.APPLICATION_JSON_VALUE + ";charset=" + StandardCharsets.UTF_8.name());
            response.setStatus(statusCode);

            // 使用OutputStream替代Writer确保编码控制
            Result error = Result.error(message);
            String json = new ObjectMapper().writeValueAsString(error);
            response.getOutputStream().write(json.getBytes(StandardCharsets.UTF_8));
        } catch (IOException ex) {
            log.error("错误响应发送失败: {}", ex.getMessage());
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            try {
                response.flushBuffer();
            } catch (IOException e) {
                log.error("响应缓冲区刷新失败: {}", e.getMessage());
            }
        }
    }
}
